#include "Camera.h"

CCamera::CCamera(void)
{
    D3DXMatrixIdentity(&m_mProjectionMatrix);
    D3DXMatrixIdentity(&m_mViewMatrix);
	D3DXMatrixIdentity(&m_mProjectionViewMatrix);
}

CCamera::~CCamera(void){}

PHMATRIX CCamera::GetProjectionViewMatrix(void)
{
	m_mProjectionViewMatrix = m_mViewMatrix * m_mProjectionMatrix;
	return m_mProjectionViewMatrix;
}

PHMATRIX CCamera::GetProjectionMatrix(void)
{
    return m_mProjectionMatrix;
}

void CCamera::SetProjectionMatrix(PHMATRIX *_mMatrix)
{
    memcpy(&m_mProjectionMatrix, _mMatrix, sizeof(PHMATRIX));
}

void CCamera::BuildPerspective(float _fFieldOfView, float _fAspectRatio, float _fZNear, float _fZFar)
{
    D3DXMatrixPerspectiveFovLH(&m_mProjectionMatrix, _fFieldOfView, _fAspectRatio, _fZNear, _fZFar);
}

PHMATRIX CCamera::GetViewMatrix(bool _bTranslate)
{
    PHMATRIX _mRotation(m_mViewMatrix), _mTransform;
    _mRotation._41 = _mRotation._42 = _mRotation._43 = 0;
    D3DXMatrixTranspose(&_mRotation, &_mRotation);
    
    D3DXMatrixIdentity(&_mTransform);
    _mTransform._41 = -(m_mViewMatrix._41);
    _mTransform._42 = -(m_mViewMatrix._42);
    _mTransform._43 = -(m_mViewMatrix._43);
    
    D3DXMatrixMultiply(&_mTransform, &_mTransform, &_mRotation);
    return (_bTranslate ? _mTransform : _mRotation);
}

void CCamera::SetViewMatrix(PHMATRIX *_mMatrix)
{
    memcpy(&m_mViewMatrix, _mMatrix, sizeof(PHMATRIX));
}

void CCamera::NormalizeViewMatrix(void)
{
    /*=================================================================
    PHVEC3 xAxis,
                yAxis(0.0f, 1.0f, 0.0f),
                zAxis(m_mViewMatrix._31, m_mViewMatrix._32, m_mViewMatrix._33);

    D3DXVec3Normalize(&zAxis, &zAxis);
    D3DXVec3Cross(&xAxis, &zAxis, &yAxis); 
    D3DXVec3Normalize(&xAxis, &xAxis);
    D3DXVec3Cross(&yAxis, &xAxis, &zAxis);
    D3DXVec3Normalize(&yAxis, &yAxis);
    
    m_mViewMatrix._11 = xAxis.x; m_mViewMatrix._12 = xAxis.y; m_mViewMatrix._13 = xAxis.z; m_mViewMatrix._14 = 0;
    m_mViewMatrix._21 = yAxis.x; m_mViewMatrix._22 = yAxis.y; m_mViewMatrix._23 = yAxis.z; m_mViewMatrix._24 = 0;
    m_mViewMatrix._31 = zAxis.x; m_mViewMatrix._32 = zAxis.y; m_mViewMatrix._33 = zAxis.z; m_mViewMatrix._34 = 0;
    //===============================================================*/
}

PHVEC3 CCamera::GetViewXAxis(void)
{
    return PHVEC3(m_mViewMatrix._11, m_mViewMatrix._12, m_mViewMatrix._13);
}

void CCamera::SetViewXAxis(PHVEC3 _vPosition)
{
    m_mViewMatrix._11 = _vPosition.x;
    m_mViewMatrix._12 = _vPosition.y;
    m_mViewMatrix._13 = _vPosition.z;
}

void CCamera::SetViewXAxis(float _fX, float _fY, float _fZ)
{
    m_mViewMatrix._11 = _fX;
    m_mViewMatrix._12 = _fY;
    m_mViewMatrix._13 = _fZ;
}

PHVEC3 CCamera::GetViewYAxis(void)
{
    return PHVEC3(m_mViewMatrix._21, m_mViewMatrix._22, m_mViewMatrix._23);
}

void CCamera::SetViewYAxis(PHVEC3 _vPosition)
{
    m_mViewMatrix._21 = _vPosition.x;
    m_mViewMatrix._22 = _vPosition.y;
    m_mViewMatrix._23 = _vPosition.z;
}

void CCamera::SetViewYAxis(float _fX, float _fY, float _fZ)
{
    m_mViewMatrix._21 = _fX;
    m_mViewMatrix._22 = _fY;
    m_mViewMatrix._23 = _fZ;
}

PHVEC3 CCamera::GetViewZAxis(void)
{
    return PHVEC3(m_mViewMatrix._31, m_mViewMatrix._32, m_mViewMatrix._33);
}

void CCamera::SetViewZAxis(PHVEC3 _vPosition)
{
    m_mViewMatrix._31 = _vPosition.x;
    m_mViewMatrix._32 = _vPosition.y;
    m_mViewMatrix._33 = _vPosition.z;
}

void CCamera::SetViewZAxis(float _fX, float _fY, float _fZ)
{
    m_mViewMatrix._31 = _fX;
    m_mViewMatrix._32 = _fY;
    m_mViewMatrix._33 = _fZ;
}

PHVEC3 CCamera::GetViewPosition(void)
{
    return PHVEC3(m_mViewMatrix._41, m_mViewMatrix._42, m_mViewMatrix._43);
}

void CCamera::SetViewPosition(PHVEC3 _vPosition)
{
    m_mViewMatrix._41 = _vPosition.x;
    m_mViewMatrix._42 = _vPosition.y;
    m_mViewMatrix._43 = _vPosition.z;
}

void CCamera::SetViewPosition(float _fX, float _fY, float _fZ)
{
    m_mViewMatrix._41 = _fX;
    m_mViewMatrix._42 = _fY;
    m_mViewMatrix._43 = _fZ;
}

/*====================================================================/
    Local Transform Functions
//===================================================================*/
void CCamera::ViewRotateLocalX(float _fAngle)
{
    PHMATRIX _mRotation;
    PHVEC3 _vLocalX(m_mViewMatrix._11, m_mViewMatrix._12, m_mViewMatrix._13);
    D3DXMatrixRotationAxis(&_mRotation, &_vLocalX, _fAngle);

    D3DXVECTOR4 Position(m_mViewMatrix._41, m_mViewMatrix._42, m_mViewMatrix._43, m_mViewMatrix._44);
    m_mViewMatrix._41 = m_mViewMatrix._42 = m_mViewMatrix._43 = 0.0f; 
    
    D3DXMatrixMultiply(&m_mViewMatrix, &m_mViewMatrix, &_mRotation);
    m_mViewMatrix._41 = Position.x; m_mViewMatrix._42 = Position.y;
    m_mViewMatrix._43 = Position.z; m_mViewMatrix._44 = Position.w;
}

void CCamera::ViewRotateLocalY(float _fAngle)
{
    PHMATRIX _mRotation;
    PHVEC3 _vLocalY(m_mViewMatrix._21, m_mViewMatrix._22, m_mViewMatrix._23);
    D3DXMatrixRotationAxis(&_mRotation, &_vLocalY, _fAngle);

    D3DXVECTOR4 Position(m_mViewMatrix._41, m_mViewMatrix._42, m_mViewMatrix._43, m_mViewMatrix._44);
    m_mViewMatrix._41 = m_mViewMatrix._42 = m_mViewMatrix._43 = 0.0f; 
    
    D3DXMatrixMultiply(&m_mViewMatrix, &m_mViewMatrix, &_mRotation);
    m_mViewMatrix._41 = Position.x; m_mViewMatrix._42 = Position.y;
    m_mViewMatrix._43 = Position.z; m_mViewMatrix._44 = Position.w;
}

void CCamera::ViewRotateLocalZ(float _fAngle)
{
    PHMATRIX _mRotation;
    PHVEC3 _vLocalZ(m_mViewMatrix._31, m_mViewMatrix._32, m_mViewMatrix._33);
    D3DXMatrixRotationAxis(&_mRotation, &_vLocalZ, _fAngle);
    
    D3DXVECTOR4 Position(m_mViewMatrix._41, m_mViewMatrix._42, m_mViewMatrix._43, m_mViewMatrix._44);
    m_mViewMatrix._41 = m_mViewMatrix._42 = m_mViewMatrix._43 = 0.0f; 
    
    D3DXMatrixMultiply(&m_mViewMatrix, &m_mViewMatrix, &_mRotation);
    m_mViewMatrix._41 = Position.x; m_mViewMatrix._42 = Position.y;
    m_mViewMatrix._43 = Position.z; m_mViewMatrix._44 = Position.w;
}

void CCamera::ViewTranslateLocal(PHVEC3 _vAxis, bool _bFPS)
{
    if (_bFPS)
    {
        ViewTranslateLocalX(_vAxis.x, _bFPS);
        ViewTranslateLocalY(_vAxis.y, _bFPS);
        ViewTranslateLocalZ(_vAxis.z, _bFPS);
        return;
    }
    
    ViewTranslateLocalX(_vAxis.x);
    ViewTranslateLocalY(_vAxis.y);
    ViewTranslateLocalZ(_vAxis.z);
}

void CCamera::ViewTranslateLocalX(float _fScale, bool _bFPS)
{
    if (_bFPS)
    {
        PHVEC3 _vTranslate((m_mViewMatrix._11), 0.0f, (m_mViewMatrix._13));
        D3DXVec3Normalize(&_vTranslate, &_vTranslate);
                                        
        m_mViewMatrix._41 += _vTranslate.x * _fScale;
        m_mViewMatrix._42 += _vTranslate.y * _fScale;
        m_mViewMatrix._43 += _vTranslate.z * _fScale;
        
        return;
    }
    m_mViewMatrix._41 += (m_mViewMatrix._11 * _fScale);
    m_mViewMatrix._42 += (m_mViewMatrix._12 * _fScale);
    m_mViewMatrix._43 += (m_mViewMatrix._13 * _fScale);
}

void CCamera::ViewTranslateLocalY(float _fScale, bool _bFPS)
{
    if (_bFPS)
    {
        PHVEC3 _vTranslate((m_mViewMatrix._21), 0.0f, (m_mViewMatrix._23));
        D3DXVec3Normalize(&_vTranslate, &_vTranslate);
                                        
        m_mViewMatrix._41 += _vTranslate.x * _fScale;
        m_mViewMatrix._42 += _vTranslate.y * _fScale;
        m_mViewMatrix._43 += _vTranslate.z * _fScale;
        
        return;
    }
    m_mViewMatrix._41 += (m_mViewMatrix._21 * _fScale);
    m_mViewMatrix._42 += (m_mViewMatrix._22 * _fScale);
    m_mViewMatrix._43 += (m_mViewMatrix._23 * _fScale);
}

void CCamera::ViewTranslateLocalZ(float _fScale, bool _bFPS)
{
    if (_bFPS)
    {
        PHVEC3 _vTranslate((m_mViewMatrix._31), 0.0f, (m_mViewMatrix._33));
        D3DXVec3Normalize(&_vTranslate, &_vTranslate);
                                        
        m_mViewMatrix._41 += _vTranslate.x * _fScale;
        m_mViewMatrix._42 += _vTranslate.y * _fScale;
        m_mViewMatrix._43 += _vTranslate.z * _fScale;
        
        return;
    }
    m_mViewMatrix._41 += (m_mViewMatrix._31 * _fScale);
    m_mViewMatrix._42 += (m_mViewMatrix._32 * _fScale);
    m_mViewMatrix._43 += (m_mViewMatrix._33 * _fScale);
}

/*====================================================================/
    Global Transform Functions
//===================================================================*/
void CCamera::ViewRotateGlobalX(float _fAngle)
{
    PHMATRIX _mRotation;
    D3DXVECTOR4 Position(m_mViewMatrix._41, m_mViewMatrix._42, m_mViewMatrix._43, m_mViewMatrix._44);
    D3DXMatrixRotationX(&_mRotation, _fAngle);
    
    m_mViewMatrix._41 = m_mViewMatrix._42 = m_mViewMatrix._43 = 0.0f; 
    
    D3DXMatrixMultiply(&m_mViewMatrix, &m_mViewMatrix, &_mRotation);
    m_mViewMatrix._41 = Position.x; m_mViewMatrix._42 = Position.y;
    m_mViewMatrix._43 = Position.z; m_mViewMatrix._44 = Position.w;
}

void CCamera::ViewRotateGlobalY(float _fAngle)
{
    PHMATRIX _mRotation;
    D3DXVECTOR4 Position(m_mViewMatrix._41, m_mViewMatrix._42, m_mViewMatrix._43, m_mViewMatrix._44);
    D3DXMatrixRotationY(&_mRotation, _fAngle);
    
    m_mViewMatrix._41 = m_mViewMatrix._42 = m_mViewMatrix._43 = 0.0f; 
    
    D3DXMatrixMultiply(&m_mViewMatrix, &m_mViewMatrix, &_mRotation);
    m_mViewMatrix._41 = Position.x; m_mViewMatrix._42 = Position.y;
    m_mViewMatrix._43 = Position.z; m_mViewMatrix._44 = Position.w;
}

void CCamera::ViewRotateGlobalZ(float _fAngle)
{
    PHMATRIX _mRotation;
    D3DXVECTOR4 Position(m_mViewMatrix._41, m_mViewMatrix._42, m_mViewMatrix._43, m_mViewMatrix._44);
    D3DXMatrixRotationZ(&_mRotation, _fAngle);
    
    m_mViewMatrix._41 = m_mViewMatrix._42 = m_mViewMatrix._43 = 0.0f; 
    
    D3DXMatrixMultiply(&m_mViewMatrix, &m_mViewMatrix, &_mRotation);
    m_mViewMatrix._41 = Position.x; m_mViewMatrix._42 = Position.y;
    m_mViewMatrix._43 = Position.z; m_mViewMatrix._44 = Position.w;
}

void CCamera::ViewTranslateGlobal(PHVEC3 _vAxis)
{
    m_mViewMatrix._41 += _vAxis.x;
    m_mViewMatrix._42 += _vAxis.y;
    m_mViewMatrix._43 += _vAxis.z;
}

void CCamera::ViewTranslateGlobalX(float _fScale)
{
    m_mViewMatrix._41 += _fScale;
}

void CCamera::ViewTranslateGlobalY(float _fScale)
{
    m_mViewMatrix._42 += _fScale;
}

void CCamera::ViewTranslateGlobalZ(float _fScale)
{
    m_mViewMatrix._43 += _fScale;
}
